package com.tcxhb.job.core.schedule;

import com.tcxhb.job.common.Thread.NamedThreadFactory;
import com.tcxhb.job.common.constants.JobApiConstants;
import com.tcxhb.job.common.model.PageRequest;
import com.tcxhb.job.core.constants.enums.OnlineStatus;
import com.tcxhb.job.core.service.job.JobMachineService;
import com.tcxhb.job.dao.dataobject.JobMachineDO;
import com.tcxhb.job.dao.dataobject.query.JobMachineQuery;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 校验机器心跳检查;
 * 机器状态在线但是2分钟未更新心跳信息,表示下线;没问题
 * @Auther: tcxhb
 * @Date: 2023/11/7
 */
@Component
@Slf4j
public class JobBeatScheduler extends BaseScheduler implements Scheduler {
    @Autowired
    private CloseableHttpAsyncClient asyncClient;
    @Autowired
    private JobMachineService machineService;

    private ScheduledExecutorService jobBeatSchedule = Executors.newScheduledThreadPool(1,
            new NamedThreadFactory("job-beat", true));
    // 间隔时间2分钟获取一次状态
    private Integer periodTime = 60;

    @PostConstruct
    @Override
    public void start() {
        jobBeatSchedule.scheduleAtFixedRate(() -> {
            try {
                scan();
            } catch (Exception e) {
                log.error("agent-check-schedule-exp", e);
            }
        }, 30, periodTime, TimeUnit.SECONDS);
    }

    public void scan() {
        Long last = 0L;
        JobMachineQuery query = buildQuery();
        while (true) {
            query.setLastId(last);
            List<JobMachineDO> list = machineService.list(query);
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            //遍历所有机器
            for (JobMachineDO machineDO : list) {
                machineOnlineCheck(machineDO);
                last = machineDO.getId();
            }
        }
    }

    /**
     * 心跳检查 状态在线但是2分钟未更新心跳信息,表示下线
     *
     * @param machineDO
     */
    public void machineOnlineCheck(JobMachineDO machineDO) {
        String url = machineDO.httpAddress() + JobApiConstants.cmd_beat;
        HttpGet get = new HttpGet(url);
        try {
            asyncClient.execute(get, new FutureCallback<HttpResponse>() {
                @Override
                public void completed(HttpResponse response) {
                    try {
                        String str = EntityUtils.toString(response.getEntity());
                        log.info("agent-beat-check:{},{},", machineDO.httpAddress(), str);
                        JobMachineDO updateDO = new JobMachineDO();
                        updateDO.setId(machineDO.getId());
                        updateDO.setStatus(OnlineStatus.online.getType());
                        updateDO.setBeatTime(new Date());
                        machineService.updateById(updateDO);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void failed(Exception e) {
                    // 在线改成离线
                    if (OnlineStatus.online.eq(machineDO.getStatus())) {
                        JobMachineDO updateDO = new JobMachineDO();
                        updateDO.setId(machineDO.getId());
                        updateDO.setStatus(OnlineStatus.offline.getType());
                        machineService.updateById(updateDO);
                    }
                }

                @Override
                public void cancelled() {
                }
            });
        } catch (Exception e) {
            log.error("agent-beat-check-exp" + url, e);
        }
    }

    /**
     * @return
     */
    private JobMachineQuery buildQuery() {
        // 在线并且心跳时间在2分钟之前的
        Long current = System.currentTimeMillis() - 1000 * 2400 * 48;
        JobMachineQuery query = new JobMachineQuery();
        query.setPage(new PageRequest());
        query.getPage().setPageNum(1000);
        query.setBeatTimeStart(new Date(current));
        query.setAscKey("id");
        return query;
    }
}
